﻿
namespace n_CWavePanel
{
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Drawing2D;

//*****************************************************
//双缓冲显示容器类
public class CWavePanel : Panel
{
	bool isMouseLeftPress;
	bool isMouseRightPress;
	
	//数据缓冲区的总长度
	const int Length = 128;
	
	//数据缓冲区
	int[][] DataBufferList;
	//通道数目
	const int CH_NUMBER = 4;
	
	//曲线相邻两点之间的横坐标, 用来调节曲线的X轴缩放
	const int XOffset = 3;
	
	//显示的字体
	Font f;
	Font f0;
	
	Color[] ChannelColorList;
	Brush[] ChannelBrushList;
	Pen[] ChannelPenList;
	
	//构造函数
	public CWavePanel(): base()
	{
		f = new Font( "Courrier New", 11 );
		f0 = new Font( "Courrier New", 10 );
		this.BackColor = Color.WhiteSmoke;
		
		this.BorderStyle = BorderStyle.None;
		SetStyle(ControlStyles.UserPaint |
		         ControlStyles.AllPaintingInWmPaint |
		         ControlStyles.OptimizedDoubleBuffer |
		         ControlStyles.ResizeRedraw |
		         ControlStyles.SupportsTransparentBackColor,true);
		
		this.Dock = DockStyle.Fill;
		this.ImeMode = ImeMode.NoControl;
		
		//初始化通道颜色列表
		ChannelColorList = new Color[ CH_NUMBER ];
		for( int i = 0; i < CH_NUMBER; ++i ) {
			ChannelColorList[ i ] = Color.Gray;
		}
		ChannelColorList[ 0 ] = Color.Red;
		ChannelColorList[ 1 ] = Color.Green;
		ChannelColorList[ 2 ] = Color.Blue;
		ChannelColorList[ 3 ] = Color.DarkGoldenrod;
		
		//初始化通道画刷列表
		ChannelBrushList = new Brush[ CH_NUMBER ];
		for( int i = 0; i < CH_NUMBER; ++i ) {
			Color c = Color.FromArgb( 100, ChannelColorList[i].R, ChannelColorList[i].G, ChannelColorList[i].B );
			ChannelBrushList[ i ] = new SolidBrush( c );
		}
		//初始化通道画笔列表
		ChannelPenList = new Pen[ CH_NUMBER ];
		for( int i = 0; i < CH_NUMBER; ++i ) {
			ChannelPenList[ i ] = new Pen( ChannelColorList[i], 5 );
		}
		
		isMouseLeftPress = false;
		isMouseRightPress = false;
		
		DataBufferList = new int[ CH_NUMBER ][];
		for( int i = 0; i < CH_NUMBER; ++i ) {
			DataBufferList[ i ] = new int[ Length ];
		}
		
		this.MouseDown += new MouseEventHandler( GPanelMouseDown );
		this.MouseUp += new MouseEventHandler( GPanelMouseUp );
		this.MouseMove += new MouseEventHandler( GPanelMouseMove );
	}
	
	//鼠标滚轮事件, 当用户在窗体上滚动鼠标滚轮的时候就会触发这个事件
	public void MWheel(object sender, MouseEventArgs e)
	{
		Invalidate();
	}
	
	//图形框鼠标按下事件, 当用户在窗体上点击鼠标按键的时候就会触发这个事件
	void GPanelMouseDown(object sender, MouseEventArgs e)
	{
		if( e.Button == MouseButtons.Left ) {
			isMouseLeftPress = true;
		}
		else {
			isMouseRightPress = true;
		}
	}
	
	//图形框鼠标松开事件, 当用户在窗体上松开鼠标按键的时候就会触发这个事件
	void GPanelMouseUp(object sender, MouseEventArgs e)
	{
		if( e.Button == MouseButtons.Left ) {
			isMouseLeftPress = false;
		}
		else {
			isMouseRightPress = false;
		}
	}
	
	//图形框鼠标移动事件, 当用户在窗体上移动鼠标的时候就会触发这个事件
	void GPanelMouseMove(object sender, MouseEventArgs e)
	{
		if( isMouseLeftPress ) {
			Invalidate();
		}
		if( isMouseRightPress ) {
			Invalidate();
		}
	}
	
	//显示刷新事件, 通过一个定时周期为1毫秒的定时器触发, 在此会判断 isOK 和 isDraw 标志,
	//如果 isOK, 则会添加一组数据并启动图形曲线刷新, 如果 isDraw, 则只启动图形曲线刷新.
	//重绘事件
	protected override void OnPaint(PaintEventArgs e)
	{
		//调整选中点, 当按下鼠标右键时, 无论是否移动鼠标, 都会自动让鼠标选中点保持固定状态
		if( isMouseRightPress ) {
			
		}
		Graphics g = e.Graphics;
		
		//清空背景
		g.Clear( this.BackColor );
		
		//绘制坐标线和网格
		DrawBack( g );
		
		//绘制所有通道的数据曲线
		for( int i = 0; i < CH_NUMBER; ++i ) {
			for( int j = 0; j < Length; ++j ) {
				int D = DataBufferList[ i ][ j ];
				
				int X = -400 + j * 20 + CH_NUMBER * 5;
				
				//绘制波形曲线
				g.DrawLine( ChannelPenList[ i ], X, this.Height - 50 - D * 4, X, this.Height - 50 );
			}
		}
		//绘制坐标原点直线
		DrawYL( g );
	}
	
	//数据添加处理函数
	public void SetChannelData( int Channel, int Data, int v )
	{
		DataBufferList[ Channel ][Data] = v;
	}
	
	//自动减弱数据
	public void AutoChange()
	{
		//绘制所有通道的数据曲线
		for( int i = 0; i < CH_NUMBER; ++i ) {
			for( int j = 0; j < Length; ++j ) {
				if( DataBufferList[ i ][ j ] > 0 ) {
					DataBufferList[ i ][ j ] -= 5;
					if( DataBufferList[ i ][ j ] < 0 ) {
						DataBufferList[ i ][ j ] = 0;
					}
				}
			}
		}
	}
	
	//绘制背景网格和标尺
	void DrawBack( Graphics g )
	{
		int YL = 0;
		
		//绘制界面上的水平的等间隔的若干行直线
		for( int i = YL; i <= this.Height; i += 20 ) {
			DrawLine( g, i );
		}
	}
	
	//绘制坐标原点直线
	void DrawYL( Graphics g )
	{
		//绘制界面上的中点线
		//g.DrawLine( Pens.Black, 0, this.Height / 2, this.Width - RightLabelWidth, this.Height / 2 );
		
		//绘制输入数据的零点线
		g.DrawLine( Pens.Black, 0, 0, this.Width, 0 );
	}
	
	//绘制一行标线和标尺, 显示基础数值, 扩展数值及单位等
	void DrawLine(  Graphics g, int y )
	{
		g.DrawLine( Pens.LightGray, 0, y, this.Width, y );
	}
}
}



